package com.company.cloud.crm.modules.mgr.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.company.cloud.common.bean.BaseClientResult;
import com.company.cloud.common.constant.BaseConstant;
import com.company.cloud.user.modules.api.response.UserSimple;
import com.company.cloud.user.modules.api.service.UserRemoteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.company.cloud.common.asserts.ValidatorUtils;
import com.company.cloud.common.bean.LoginSimpleUserInfo;
import com.company.cloud.common.constant.BaseConstant.EnabledEnum;
import com.company.cloud.common.constant.BaseConstant.YNEnum;
import com.company.cloud.common.constant.BaseReturnEnum;
import com.company.cloud.common.exception.BusinessException;
import com.company.cloud.common.utils.CheckUtils;
import com.company.cloud.crm.constant.CrmBizConstant.AllocationStateEnum;
import com.company.cloud.crm.modules.base.entity.CustomerAllocationLog;
import com.company.cloud.crm.modules.base.entity.CustomerContactInfo;
import com.company.cloud.crm.modules.base.entity.CustomerInfo;
import com.company.cloud.crm.modules.base.service.CustomerAllocationLogService;
import com.company.cloud.crm.modules.base.service.CustomerContactInfoService;
import com.company.cloud.crm.modules.base.service.CustomerInfoService;
import com.company.cloud.crm.modules.cache.models.CustomerModel;
import com.company.cloud.crm.modules.cache.utils.CrmBizChangeUtils;
import com.company.cloud.crm.modules.mgr.controller.req.CustomerAllocationParam;
import com.company.cloud.crm.modules.mgr.controller.req.CustomerBackParam;
import com.company.cloud.crm.modules.mgr.controller.req.CustomerSaveParam;
import com.company.cloud.crm.modules.mgr.controller.req.CustomerUpdateParam;
import com.company.cloud.crm.modules.mgr.service.CustomerMgrService;
import com.company.cloud.crm.utils.CrmBizId;

import cn.hutool.core.bean.BeanUtil;
import io.swagger.annotations.ApiModelProperty;

@Service
public class CustomerMgrServiceImpl implements CustomerMgrService{

	@Autowired
	private CustomerInfoService customerInfoService;
	@Autowired
	private CustomerAllocationLogService customerAllocationLogService;
	@Autowired
	private CustomerContactInfoService  customerContactInfoService;
	@Autowired
	private UserRemoteService userRemoteService;
	
	@Transactional
	@Override
	public void save(CustomerSaveParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		CustomerInfo entity=new CustomerInfo();
		entity.setCustNo(CrmBizId.getCustomerNo());
		entity.setCompanyNo(userInfo.getCompanyNo());
		entity.setSaleLeadId(params.getSaleLeadId());
		entity.setUserId(params.getUserId());
		entity.setName(params.getName());
		entity.setGrade(params.getGrade());
		entity.setSourceOne(params.getSourceOne());
		entity.setSourceTwo(params.getSourceTwo());
		entity.setIndustryOne(params.getIndustryOne());
		entity.setIndustryTwo(params.getIndustryTwo());
		entity.setTel(params.getTel());
		entity.setMail(params.getMail());
		entity.setFax(params.getFax());
		entity.setWebsiteUrl(params.getWebsiteUrl());
		entity.setMobile(params.getMobile());
		entity.setRemark(params.getRemark());
		entity.setNationCode(params.getNationCode());
		entity.setProvince(params.getProvince());
		entity.setCity(params.getCity());
		entity.setRegion(params.getRegion());
		entity.setStreet(params.getStreet());
		entity.setAddr(params.getAddr());
		entity.setLongitude(params.getLongitude());
		entity.setLatitude(params.getLatitude());
		
		if(CheckUtils.hasInt(params.getSaleUserId())) {
			entity.setSaleUserId(params.getSaleUserId());
			entity.setAllocationState(AllocationStateEnum.Yes_Allocation.getCode());
		}else {
			entity.setAllocationState(AllocationStateEnum.Not_Allocation.getCode());
		}
		entity.addCreateParam(userInfo);
		entity.addEditParam(userInfo);
		customerInfoService.save(entity);
		
		if(AllocationStateEnum.Yes_Allocation.getCode().equals(entity.getAllocationState())) {
			CustomerAllocationLog log=new CustomerAllocationLog();
			log.setId(CrmBizId.getCustomerAllocationLogId());
			log.setCompanyNo(entity.getCompanyNo());
			log.setCustNo(entity.getCustNo());
			log.setAllocationUserId(entity.getSaleUserId());
			log.setStartDate(LocalDateTime.now());
			log.setAllocationOpUserId(userInfo.getId());
			log.setAllocationOpDate(LocalDateTime.now());
			log.setAllocationOpIp(userInfo.getIp());
			log.addCreateParam(userInfo);
			log.addEditParam(userInfo);
			customerAllocationLogService.save(log);
			
			CustomerContactInfo contact=new CustomerContactInfo();
			contact.setUserId(entity.getUserId());
			contact.setCustNo(entity.getCustNo());
			contact.setContactUserId(entity.getSaleUserId());
			contact.setIsExclusiveContact(YNEnum.YES.getCode());
			contact.addCreateParam(userInfo);
			contact.addEditParam(userInfo);
			customerContactInfoService.save(contact);
		}
		
	}
	
	@Override
	public void update(CustomerUpdateParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		CustomerInfo entity= customerInfoService.getById(params.getCustNo());
		if(entity==null || EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		entity.setName(params.getName());
		entity.setGrade(params.getGrade());
		entity.setSourceOne(params.getSourceOne());
		entity.setSourceTwo(params.getSourceTwo());
		entity.setIndustryOne(params.getIndustryOne());
		entity.setIndustryTwo(params.getIndustryTwo());
		entity.setTel(params.getTel());
		entity.setMail(params.getMail());
		entity.setFax(params.getFax());
		entity.setWebsiteUrl(params.getWebsiteUrl());
		entity.setMobile(params.getMobile());
		entity.setRemark(params.getRemark());
		entity.setNationCode(params.getNationCode());
		entity.setProvince(params.getProvince());
		entity.setCity(params.getCity());
		entity.setRegion(params.getRegion());
		entity.setStreet(params.getStreet());
		entity.setAddr(params.getAddr());
		entity.setLongitude(params.getLongitude());
		entity.setLatitude(params.getLatitude());
		entity.addEditParam(userInfo);
		customerInfoService.updateById(entity);
//		CrmProducerUtils.updateObj(IRelBusiType.CRM_Customer,oldEntity, entity, userInfo);
	}
	@Override
	public void del(String custNo, LoginSimpleUserInfo userInfo) {
		CustomerInfo entity= customerInfoService.getById(custNo);
		if(entity==null || EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		entity.setRowsState(EnabledEnum.DISABLED.getCode());
		entity.addEditParam(userInfo);
		customerInfoService.updateById(entity);
		
	}
	@Override
	public CustomerModel get(String custNo) {
		CustomerInfo entity= customerInfoService.getById(custNo);
		if(entity==null || EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		UserSimple  userSimple=null;
		if(CheckUtils.hasInt(entity.getUserId())){
			BaseClientResult<UserSimple> userSimpleResp = userRemoteService.getUserById(entity.getUserId());
			userSimple=BaseClientResult.getResultData(userSimpleResp);
		}
		return CrmBizChangeUtils.getCustomer(entity,userSimple);
	}

	@Override
	public CustomerModel getByUserId(Integer userId) {
		List<CustomerInfo> customerList = customerInfoService.list(new QueryWrapper<CustomerInfo>()
				.eq("user_id", userId)
				.eq("rows_state", EnabledEnum.ENABLED.getCode())
		);
		if (CollectionUtils.isEmpty(customerList)) {
			return null;
		} else {
			return get(customerList.get(0).getCustNo()) ;
		}
	}
	
	@Transactional
	@Override
	public void allocationByPool(CustomerAllocationParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		List<CustomerInfo> custList=customerInfoService.list(
				new QueryWrapper<CustomerInfo>()
				.in("cust_no", params.getCustNos()));
		if(CollectionUtils.isEmpty(custList)) {
			throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
		}
		
		List<CustomerAllocationLog> logList=new ArrayList<CustomerAllocationLog>();
		for(CustomerInfo cust:custList) {
			if(cust.getCompanyNo().equals(userInfo.getCompanyNo())) {
				throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
			}
			if(AllocationStateEnum.Yes_Allocation.getCode().equals(cust.getAllocationState())) {
				throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
			}
			CustomerAllocationLog log=new CustomerAllocationLog();
			log.setId(CrmBizId.getCustomerAllocationLogId());
			log.setCompanyNo(cust.getCompanyNo());
			log.setCustNo(cust.getCustNo());
			log.setAllocationUserId(params.getSaleUserId());
			log.setStartDate(LocalDateTime.now());
			log.setAllocationOpUserId(userInfo.getId());
			log.setAllocationOpDate(LocalDateTime.now());
			log.setAllocationOpIp(userInfo.getIp());
			log.addCreateParam(userInfo);
			log.addEditParam(userInfo);
			logList.add(log);
		}
		
		if(logList.size()>0) {
			customerInfoService.update(new UpdateWrapper<CustomerInfo>()
					.set("sale_user_id", params.getSaleUserId())
					.set("allocation_state", AllocationStateEnum.Yes_Allocation.getCode())
					.set("allocation_op_user_id", userInfo.getId())
					.set("allocation_op_date", LocalDateTime.now())
					.in("cust_no", params.getCustNos())
					);
			customerAllocationLogService.saveBatch(logList);
		}
	}
	
	@Transactional
	@Override
	public void backByPool(CustomerBackParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		List<CustomerInfo> custList=customerInfoService.list(
				new QueryWrapper<CustomerInfo>()
				.in("cust_no", params.getCustNos()));
		if(CollectionUtils.isEmpty(custList)) {
			throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
		}
		List<CustomerAllocationLog> logList=customerAllocationLogService.list(
				new QueryWrapper<CustomerAllocationLog>()
				.in("cust_no", params.getCustNos())
				.isNull("end_date")
				);
		if(CollectionUtils.isEmpty(logList)) {
			throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
		}
		
		Map<String, CustomerAllocationLog> logMap=new HashMap<String, CustomerAllocationLog>();
		logList.forEach(item->{
			logMap.put(item.getCustNo(), item);
		});
		
		List<CustomerInfo> updateCustList=new ArrayList<CustomerInfo>();
		List<CustomerAllocationLog> updateLogList=new ArrayList<CustomerAllocationLog>();
		
		LocalDateTime endDate=LocalDateTime.now();
		for(CustomerInfo cust:custList) {
			if(cust.getCompanyNo().equals(userInfo.getCompanyNo())) {
				throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
			}
			if(AllocationStateEnum.Not_Allocation.getCode().equals(cust.getAllocationState())) {
				throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
			}
			CustomerAllocationLog log= logMap.get(cust.getCustNo());
			if(log==null) {
				throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
			}
			cust.setSaleUserId(null);
			cust.setAllocationState(AllocationStateEnum.Not_Allocation.getCode());
			cust.addEditParam(userInfo);
			updateCustList.add(cust);
			
			log.setEndDate(endDate);
			log.setBackReason(params.getBackReason());
			log.setBackOpDate(endDate);
			log.setBackOpUserId(userInfo.getId());
			log.setBackOpIp(userInfo.getIp());
			log.addEditParam(userInfo);
			updateLogList.add(log);
		}
		
		if(updateCustList.size()>0) {
			customerInfoService.updateBatchById(updateCustList);
		}
		if(updateLogList.size()>0) {
			customerAllocationLogService.updateBatchById(updateLogList);
		}
		
	}

	@Override
	public void allocation(CustomerAllocationParam params, LoginSimpleUserInfo userInfo) {
		for(String custNo:params.getCustNos()) {
			this.allocation(custNo, params.getSaleUserId(), userInfo);
		}
	}

	@Transactional
	@Override
	public void allocation(String custNo, Integer userId, LoginSimpleUserInfo userInfo) {
		CustomerInfo entity= customerInfoService.getById(custNo);
		if(entity==null || EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		
		entity.setSaleUserId(userId);
		entity.setAllocationState(AllocationStateEnum.Yes_Allocation.getCode());
		entity.addEditParam(userInfo);
		customerInfoService.updateById(entity);
		
		CustomerAllocationLog oldLog= customerAllocationLogService.getOne(new QueryWrapper<CustomerAllocationLog>()
				.eq("cust_no", custNo)
				.isNull("end_date")
				);
		if(oldLog!=null) {
			oldLog.setEndDate(LocalDateTime.now());
			oldLog.setBackOpDate(LocalDateTime.now());
			oldLog.setBackOpIp(userInfo.getIp());
			oldLog.setBackOpUserId(userInfo.getId());
			oldLog.addEditParam(userInfo);
			customerAllocationLogService.updateById(oldLog);
		}
		
		CustomerAllocationLog log=new CustomerAllocationLog();
		log.setId(CrmBizId.getCustomerAllocationLogId());
		log.setCompanyNo(entity.getCompanyNo());
		log.setCustNo(entity.getCustNo());
		log.setAllocationUserId(entity.getSaleUserId());
		log.setStartDate(LocalDateTime.now());
		log.setAllocationOpUserId(userInfo.getId());
		log.setAllocationOpDate(LocalDateTime.now());
		log.setAllocationOpIp(userInfo.getIp());
		log.addCreateParam(userInfo);
		log.addEditParam(userInfo);
		customerAllocationLogService.save(log);
		
		CustomerContactInfo contact=customerContactInfoService.getOne(new QueryWrapper<CustomerContactInfo>()
				.eq("cust_no", entity.getCustNo())
				.eq("contact_user_id", entity.getSaleUserId())
				);
		if(contact==null) {
			contact=new CustomerContactInfo();
			contact.setUserId(entity.getUserId());
			contact.setCustNo(entity.getCustNo());
			contact.setContactUserId(entity.getSaleUserId());
			contact.setIsExclusiveContact(YNEnum.NO.getCode());
			contact.addCreateParam(userInfo);
			contact.addEditParam(userInfo);
			customerContactInfoService.save(contact);
		}
	}
	
	
}
